﻿using System;

namespace IceCS.DataStructure.Core.String
{
    /// <summary>
    /// 顺序串
    /// </summary>
    public class SequenceString : IString<SequenceString>
    {
        public char[] Data;

        #region ctor
        public SequenceString(int len)
        {
            Data = new char[len];
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="arr"></param>
        public SequenceString(char[] arr) : this(arr.Length)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                Data[i] = arr[i];
            }
        }

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public char this[int index]
        {
            get
            {
                return Data[index];
            }
            set
            {
                Data[index] = value;
            }
        }

        SequenceString IString<SequenceString>.this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

        /// <summary>
        /// 
        /// </summary>
        public int Length => Data.Length;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public int Compare(SequenceString str)
        {
            int len = this.Length <= str.Length ? this.Length : str.Length;
            int i;
            for (i = 0; i < len; i++)
            {
                if (this[i] == str[i])
                {
                    break;
                }
            }

            if (i < len)
            {
                if (this[i] < str[i])
                {
                    return -1;
                }
                else
                {
                    return 1;
                }
            }

            if (this.Length == str.Length)
            {
                return 0;
            }

            if (this.Length < str.Length)
            {
                return -1;
            }

            else
            {
                return 1;
            }
        }

        public SequenceString Concat(SequenceString s)
        {
            SequenceString s1 = new SequenceString(this.Length + s.Length);
            for (int i = 0; i < this.Length; i++)
            {
                s1.Data[i] = this[i];
            }
            for (int i = 0; i < s.Length; i++)
            {
                s1.Data[this.Length + i] = s[i];
            }
            return s1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public SequenceString Delete(int index, int len)
        {
            var cond1 = index < 0;
            var cond2 = index > this.Length - 1;
            var cond3 = len <= 0;
            var cond4 = len > this.Length - index;
            if (cond1 || cond2 || cond3 || cond4)
            {
                //Console.WriteLine("position is error");
                return null;
            }

            SequenceString s = new SequenceString(this.Length - len);
            int j = 0;
            for (int i = 0; i < index; i++)
            {
                s[j++] = this[i];
            }
            for (int i = index + len; i < this.Length; i++)
            {
                s[j++] = this[i];
            }
            return s;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public int IndexOf(SequenceString s, int startpos)
        {
            SequenceString sub;
            sub = this.SubString(startpos, this.Length - startpos);
            if (sub.Length < s.Length)
            {
                //Console.WriteLine("this is not string s !");
                return -1;
            }
            int i, j, v;
            i = 0;
            j = 0;
            while (i < sub.Length && j < s.Length)
            {
                if (sub.Data[i] == s.Data[j])
                {
                    i++;
                    j++;
                }
                else
                {
                    i = i - j + 1;
                    j = 0;
                }
            }
            if (j == s.Length)
            {
                v = i - s.Length + startpos;
            }
            else
            {
                v = -1;
            }
            return v;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public int LastIndexOf(SequenceString s)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        public SequenceString Insert(int index, SequenceString s)
        {
            int len = s.Length;
            int len2 = len + this.Length;
            SequenceString s1 = new SequenceString(len2);
            if (index < 0 || index > this.Length - 1)
            {
                //Console.WriteLine("position error");
                return null;
            }
            for (int i = 0; i < index; i++)
            {
                s1[i] = this[i];
            }
            for (int i = 0; i < index + len; i++)
            {
                s1[i] = s[i - index];
            }
            for (int i = index + len; i < len2; i++)
            {
                s1[i] = this[i - len];
            }
            return s1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="start"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public SequenceString SubString(int start, int length)
        {
            var cond1 = start < 0;
            var cond2 = start > this.Length - 1;
            var cond3 = length <= 0;
            var cond4 = length > this.Length - start;
            if (cond1 || cond2 || cond3 || cond4)
            {
                return null;
            }
            SequenceString str = new SequenceString(length);
            for (int i = 0; i < length; i++)
            {
                str[i] = this[start + i];
            }
            return str;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return new string(Data);
        }
    }
}
